package com.ruoyi.trainingManagement.controller;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;

import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.impl.SysDeptServiceImpl;
import com.ruoyi.trainingManagement.domain.*;
import com.ruoyi.trainingManagement.domain.Vo.TrainingProgramWithCoursesDTO;
import com.ruoyi.trainingManagement.service.IFirstLevelDisciplineService;
import com.ruoyi.trainingManagement.service.impl.TrainingCreditServiceImpl;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.trainingManagement.service.ItrainingProgramService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

import static com.ruoyi.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * 培养方案管理Controller
 *
 * @author chenxl
 * @date 2025-04-15
 */
@RestController
@RequestMapping("/trainingManagement/trainingManagement")
public class trainingProgramController extends BaseController
{
    @Autowired
    private ItrainingProgramService trainingProgramService;
    @Autowired
    private trainingProgramCoursesController trainingProgramCoursesController;

    @Autowired
    private IFirstLevelDisciplineService firstLevelDisciplineService;
    @Autowired
    private com.ruoyi.trainingManagement.service.impl.trainingProgramCoursesServiceImpl trainingProgramCoursesServiceImpl;
    @Autowired
    private TrainingCreditServiceImpl trainingCreditService;

    /**
     * 查询培养方案管理列表
     */
    //@PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:list')")
    @GetMapping("/list")
    public TableDataInfo list(trainingProgram trainingProgram)
    {   //  打印查询参数
//        System.out.println("查询参数：" + trainingProgram);
//        List<Long> roleDeptIds = sysDeptService.getRoleDeptIds();
//        System.out.println("获取到的部门id列表roleDeptIds：" + roleDeptIds);
        //if ()
        startPage();
        List<trainingProgram> list = trainingProgramService.selecttrainingProgramList(trainingProgram);
        //打印查询到的数据
        System.out.println("查询到的数据：" + list);
        return getDataTable(list);
    }

    /**
     * 导出培养方案管理列表
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:export')")
    @Log(title = "培养方案管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, trainingProgram trainingProgram)
    {
        List<trainingProgram> list = trainingProgramService.selecttrainingProgramList(trainingProgram);
        ExcelUtil<trainingProgram> util = new ExcelUtil<trainingProgram>(trainingProgram.class);
        util.exportExcel(response, list, "培养方案管理数据");
    }

    /**
     * 获取培养方案管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") String id)
    {
        return success(trainingProgramService.selecttrainingProgramById(id));
    }

    /**
     * 新增培养方案管理
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:add')")
    @Log(title = "培养方案管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody trainingProgram trainingProgram) {
        try {
            //course.setId(IdUtils.fastSimpleUUID());
            trainingProgram.setId(IdUtils.fastSimpleUUID());
            trainingProgram insertedProgram = trainingProgramService.inserttrainingProgram(trainingProgram);
            if (insertedProgram != null && insertedProgram.getId() != null) {
                return AjaxResult.success("新增成功", insertedProgram);
            } else {
                return AjaxResult.error("新增培养方案失败，未能保存数据或获取ID");
            }
        } catch (Exception e) {
            System.err.println("新增培养方案时发生异常: " + e.getMessage());
            // logger.error("新增培养方案时发生异常", e); // 使用规范的日志记录器
            return AjaxResult.error("新增培养方案时发生错误: " + e.getMessage());
        }
    }


    /**
     * 修改培养方案管理
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:edit')")
    @Log(title = "培养方案管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody trainingProgram trainingProgram) throws IOException {
        // 使用您提供的Excel文件路径
        String excelFilePath = "C:/Users/86178/Desktop/学科目录.xlsx";
        FileInputStream inputStream = new FileInputStream(excelFilePath);
        Workbook workbook = new XSSFWorkbook(inputStream);
        System.out.println("开始读取数据");
        // 获取第一个工作表
        Sheet sheet = workbook.getSheetAt(0);
        System.out.println("获取第一个工作表"+sheet.getSheetName());
        int count = 0;
        // 从第二行开始（跳过标题行）
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            FirstLevelDiscipline discipline = new FirstLevelDiscipline();
            Row row = sheet.getRow(i);
            if (row == null) continue;

//            // 生成唯一ID
//            String id = UUID.randomUUID().toString();
            discipline.setId(IdUtils.fastSimpleUUID());
            // 获取单元格数据
            String code = getCellValue(row.getCell(0));    // A列：学科代码
            String name = getCellValue(row.getCell(1));    // B列：学科名称
            String desc = getCellValue(row.getCell(2));    // C列：描述
            discipline.setDisciplineCode(code);
            discipline.setDisciplineName(name);
            discipline.setDescription(desc);
            discipline.setCreateTime(new Date());
            firstLevelDisciplineService.insertFirstLevelDiscipline( discipline);
            count++;
            System.out.println("插入第"+count+"行结果");
        }


        return toAjax(trainingProgramService.updatetrainingProgram(trainingProgram));
    }

    /**
     * 删除培养方案管理
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:remove')")
    @Log(title = "培养方案管理", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable String[] ids)
    {
        return toAjax(trainingProgramService.deletetrainingProgramByIds(ids));
    }
    /**
     * 新增培养方案及其关联课程 (推荐的新方法，原子操作)
     * 这个方法期望接收一个匹配 TrainingProgramWithCoursesDTO 结构的 JSON 请求体。
     * 它调用单个服务层方法来负责事务性保存。
     *
     * @param dto 包含培养方案及其课程的数据传输对象
     * @return AjaxResult 包含新创建的培养方案（带ID）或错误消息。
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:trainingManagement:add')") // 确保权限正确
    @Log(title = "培养方案及课程", businessType = BusinessType.INSERT) // 日志标题反映组合操作
    @PostMapping("/withCourses") // 使用一个清晰、不同的路径
    public AjaxResult createProgramWithCourses(@Validated @RequestBody TrainingProgramWithCoursesDTO dto) {
        System.out.println("------------------------------------");
        System.out.println("获取课程数据: " + dto.getCourses()+"获取培养方案数据: "+dto.getProgram()+"获取到的培养方案学科信息"+dto.getDisciplinesData());
        System.out.println("------------------------------------");
        try {
            if (dto == null || dto.getProgram() == null) {
                return AjaxResult.error("请求数据无效: 缺少培养方案基本信息");
            }
            // 从 DTO 中提取数据
            trainingProgram programToCreate = dto.getProgram();
            System.out.println("获取培养方案数据: " + programToCreate);
            TrainingCredit credit = dto.getCredit();
            System.out.println("获取培养方案学分数据: " + credit);
            List<trainingProgramCourses> coursesToCreate = dto.getCourses();
            System.out.println("获取课程数据: " + coursesToCreate);
            List<TrainingProgramSubject> subjectsToCreate = dto.getDisciplinesData();
            trainingProgram savedProgram = trainingProgramService.createProgramWithCourses(programToCreate,credit, coursesToCreate, subjectsToCreate);
            return AjaxResult.success("新增培养方案及课程成功", savedProgram);
        } catch (Exception e) {
            System.err.println("新增培养方案及课程时发生异常: " + e.getMessage());
            return AjaxResult.error("新增培养方案及课程失败: " + e.getMessage());
        }
    }

    /**
     * 更新培养方案及其关联课程
     */
    @Transactional(rollbackFor = Exception.class)
    @PutMapping("/withCourses")
    public AjaxResult updateProgramWithCourses(@Valid @RequestBody TrainingProgramWithCoursesDTO dto) {
        // 日志打印优化：避免对象直接toString导致的冗余信息
        log.info("开始更新培养方案：ID={}, 课程数量={}, 学分数据是否存在={}",
                dto.getProgram() != null ? dto.getProgram().getId() : "null",
                dto.getCourses() != null ? dto.getCourses().size() : 0,
                dto.getCredit() != null);

        try {
            // 1. 校验核心参数
            if (dto.getProgram() == null || dto.getProgram().getId() == null) {
                return AjaxResult.error("培养方案ID不能为空");
            }

            // 2. 更新培养方案主表
            int programUpdateCount = trainingProgramService.updatetrainingProgram(dto.getProgram());
            if (programUpdateCount <= 0) {
                log.warn("未找到需更新的培养方案：ID={}", dto.getProgram().getId());
                // 可根据业务需求选择抛出异常或继续执行
                // throw new BusinessException("未找到对应的培养方案");
            }

            // 3. 处理课程关联（新增/更新/删除）
            List<trainingProgramCourses> coursesToUpdate = dto.getCourses();
            if (coursesToUpdate != null) {
                // 3.1 获取原有课程ID列表（用于对比删除）
                List<trainingProgramCourses> existingCourses = trainingProgramCoursesServiceImpl
                        .selecttrainingProgramCoursesByTrainingProgramId(dto.getProgram().getId());
                List<String> existingCourseIds = existingCourses.stream()
                        .map(trainingProgramCourses::getId)
                        .collect(Collectors.toList());

                // 3.2 获取当前提交的课程ID列表（过滤空ID的新增课程）
                List<String> currentCourseIds = coursesToUpdate.stream()
                        .filter(course -> course.getId() != null && !course.getId().isEmpty())
                        .map(trainingProgramCourses::getId)
                        .collect(Collectors.toList());

                // 3.3 计算需要删除的课程ID（原有存在但当前未提交的）
                List<String> coursesToDelete = existingCourseIds.stream()
                        .filter(id -> !currentCourseIds.contains(id))
                        .collect(Collectors.toList());

                // 3.4 执行删除操作
                if (!coursesToDelete.isEmpty()) {
                    int deleteCount = trainingProgramCoursesServiceImpl
                            .deletetrainingProgramCoursesByIds(coursesToDelete.toArray(new String[0]));
                    log.info("删除培养方案关联课程：数量={}, IDs={}", deleteCount, coursesToDelete);
                }

                // 3.5 执行新增/更新操作
                for (trainingProgramCourses course : coursesToUpdate) {
                    // 强制绑定当前培养方案ID，避免数据错乱
                    course.setTrainingProgramId(dto.getProgram().getId());

                    if (course.getId() == null || course.getId().isEmpty()) {
                        // 新增课程：生成UUID
                        course.setId(IdUtils.fastSimpleUUID());
                        int insertCount = trainingProgramCoursesServiceImpl.inserttrainingProgramCourses(course);
                        log.debug("新增课程成功：ID={}", course.getId());
                    } else {
                        // 更新课程
                        int updateCount = trainingProgramCoursesServiceImpl.updatetrainingProgramCourses(course);
                        log.debug("更新课程：ID={}, 影响行数={}", course.getId(), updateCount);
                    }
                }
            }

            // 4. 更新学分数据（若存在）
            if (dto.getCredit() != null) {
                // 确保学分数据与培养方案关联（若需要）
                // dto.getCredit().setProgramId(dto.getProgram().getId());
                int creditUpdateCount = trainingCreditService.updateTrainingCredit(dto.getCredit());
                log.info("更新学分数据：影响行数={}", creditUpdateCount);
            }

            return AjaxResult.success("更新培养方案及关联课程成功");
        } catch (Exception e) {
            // 捕获系统异常，记录详细日志
            log.error("更新培养方案失败", e);
            return AjaxResult.error("系统异常：更新失败，请联系管理员");
        }
    }


    // 获取单元格值的辅助方法
    private static String getCellValue(Cell cell) {
        if (cell == null) return "";

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue().trim();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf((int) cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }
    /**调用updateStatusById根据培养方案id更新培养方案的status/**
     * 批量根据ID更新状态
     *
     * @param ids 单个培养方案ID
     * @param status 要更新的状态值
     * @return 影响行数
     */
    @PostMapping("/updateStatusById")  // 将PutMapping改为PostMapping
    public AjaxResult updateStatusById(@RequestParam("ids") String ids, @RequestParam("status") Integer status) {
        return trainingProgramService.updateStatusById(ids, status) > 0 ? AjaxResult.success() : AjaxResult.error();
    }
}

